package aliyun

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"

	openapi "github.com/alibabacloud-go/darabonba-openapi/client"
	slb20140515 "github.com/alibabacloud-go/slb-20140515/v3/client"
	util "github.com/alibabacloud-go/tea-utils/service"
	"github.com/sirupsen/logrus"

	"gitee.com/bjf-fhe/apicat/entry"
	"gitee.com/bjf-fhe/apicat/notify"
	"github.com/alibabacloud-go/tea/tea"
)

type Handler struct {
	client  *slb20140515.Client
	cfg     *notify.Config
	ncfg    *openapi.Config
	existed map[string]*entry.LogEntry
	dest    string
	destV6  string
}

func createClient(ncfg *openapi.Config) (_result *slb20140515.Client, _err error) {

	// 访问的域名
	ncfg.Endpoint = tea.String("slb.aliyuncs.com")
	_result = &slb20140515.Client{}
	_result, _err = slb20140515.NewClient(ncfg)
	return _result, _err
}

func (h *Handler) Init(cfg *notify.Config, ncfg *openapi.Config, dest, destv6 string) (err error) {

	h.client, err = createClient(ncfg)

	if err != nil {
		return
	}

	h.cfg = cfg
	h.ncfg = ncfg
	h.dest = dest
	h.destV6 = destv6

	h.existed = make(map[string]*entry.LogEntry)

	if h.dest != "" {
		err := h.fetchAcls(h.dest)
		if err != nil {
			return err
		}
	} else if h.destV6 == "" {
		return errors.New("Dest没有设置，请使用--aliyun-dest配置该参数")
	}

	if h.destV6 != "" {
		err := h.fetchAcls(h.destV6)
		if err != nil {
			return err
		}
	}

	return err
}

func (h *Handler) fetchAcls(aclId string) (err error) {
	describeAccessControlListAttributeRequest := &slb20140515.DescribeAccessControlListAttributeRequest{
		RegionId: h.ncfg.RegionId,
		AclId:    &aclId,
	}
	runtime := &util.RuntimeOptions{}

	var result *slb20140515.DescribeAccessControlListAttributeResponse
	result, err = h.client.DescribeAccessControlListAttributeWithOptions(describeAccessControlListAttributeRequest, runtime)

	if err == nil && result.Body.AclEntrys != nil {
		for _, inServer := range result.Body.AclEntrys.AclEntry {
			var logEntry entry.LogEntry
			json.Unmarshal([]byte(*inServer.AclEntryComment), &logEntry)
			h.existed[*inServer.AclEntryIP] = &logEntry
		}
	}
	return err
}

type AclEntrys []AclEntry

type AclEntry struct {
	Entry   string `json:"entry"`
	Comment string `json:"comment"`
}

func (h *Handler) toEntrys(item *entry.LogEntry) (string, error) {
	var entrys AclEntrys
	var entry = AclEntry{
		Entry: item.Client + "/32",
	}
	entry.Comment = item.Description()
	entrys = append(entrys, entry)

	bts, err := json.Marshal(entrys)
	if err == nil {
		return string(bts), nil
	}
	return "", err
}

func (h *Handler) NotifyAdd(toAdd *entry.LogEntry) error {
	if _, existed := h.existed[toAdd.Client]; existed {
		logrus.Info(toAdd.Client, "已经存在")
		return nil
	}

	if toAdd.Count < int64(h.cfg.MinCount) && toAdd.ErrorType < entry.EntryError(h.cfg.MinLevel) {
		logrus.Info(toAdd.Client, "条目未达到拦截规则需要")
		return nil
	}

	ip := net.ParseIP(toAdd.Client)

	var dest string

	if ip.To4() == nil {
		dest = h.destV6
	} else {
		dest = h.dest
	}

	entrys, err := h.toEntrys(toAdd)
	if err != nil {
		return err
	}

	fmt.Println(entrys)
	// entrys = `[{"entry":"10.0.1.1","comment":"privaterule1"},{"entry":"192.168.1.1","comment":"privaterule2"}]`

	_, err = h.client.AddAccessControlListEntryWithOptions(&slb20140515.AddAccessControlListEntryRequest{
		RegionId:  h.ncfg.RegionId,
		AclId:     &dest,
		AclEntrys: &entrys,
	}, &util.RuntimeOptions{})

	return err
}

func (h *Handler) NotifyDel(toAdd *entry.LogEntry) error {
	logrus.Fatal("TODO Del")
	return nil
}
